using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
using Verse.AI.Group;
using Verse.Noise;

namespace RimWorld{
public enum PsychicDroneLevel : byte
{
	None,

	GoodMedium,

	BadLow,
	BadMedium,
	BadHigh,
	BadExtreme
}


class Building_PsychicEmanator : Building_CrashedShipPart
{
	//Working vars
	private int					ticksToInsanityPulse;
	private int					ticksToIncreaseDroneLevel;
	public PsychicDroneLevel	droneLevel = PsychicDroneLevel.BadLow;

	//Constants
	private const int			DroneLevelIncreaseInterval = (int)(GenDate.TicksPerDay * 2.5f);
    private static readonly		IntRange InsanityPulseInterval = new IntRange( GenDate.TicksPerDay, (int)(GenDate.TicksPerDay * 2.5f));
    private const int			AnimalInsaneRadius = 25;

    //Properties
    protected override float PlantHarmRange
    {
        get
        {
            return Mathf.Min(3f + 40f * ((float)age / GenDate.TicksPerDay), 20f);
        }
    }

	public override void SpawnSetup(Map map)
    {
        base.SpawnSetup(map);

        ticksToInsanityPulse = InsanityPulseInterval.RandomInRange;
		ticksToIncreaseDroneLevel = DroneLevelIncreaseInterval;

        if( map == Find.VisibleMap )
		    SoundDefOf.PsychicPulseGlobal.PlayOneShotOnCamera();
    }

    public override void ExposeData()
    {
        base.ExposeData();

        Scribe_Values.LookValue(ref ticksToInsanityPulse, "ticksToInsanityPulse");
        Scribe_Values.LookValue(ref ticksToIncreaseDroneLevel, "ticksToIncreaseDroneLevel");
        Scribe_Values.LookValue(ref droneLevel, "droneLevel");
    }

    public override string GetInspectString()
    {
        StringBuilder str = new StringBuilder();
        str.AppendLine(base.GetInspectString());

		string droneLevelString = "Error";
		switch( droneLevel )
		{
			case PsychicDroneLevel.BadLow: droneLevelString = "PsychicDroneLevelLow".Translate();
				break;
			case PsychicDroneLevel.BadMedium: droneLevelString = "PsychicDroneLevelMedium".Translate();
				break;
			case PsychicDroneLevel.BadHigh: droneLevelString = "PsychicDroneLevelHigh".Translate();
				break;
			case PsychicDroneLevel.BadExtreme: droneLevelString = "PsychicDroneLevelExtreme".Translate();
				break;
		}

		str.AppendLine("PsychicDroneLevel".Translate( droneLevelString ) );

        return str.ToString();
    }

    public override void Tick()
    {
        base.Tick();

        ticksToInsanityPulse--;
		if (ticksToInsanityPulse <= 0 )
		{
			DoAnimalInsanityPulse();
			ticksToInsanityPulse = InsanityPulseInterval.RandomInRange;
		}

		ticksToIncreaseDroneLevel--;
		if( ticksToIncreaseDroneLevel <= 0 )
		{
			IncreaseDroneLevel();
			ticksToIncreaseDroneLevel = DroneLevelIncreaseInterval;
		}
    }

	private void IncreaseDroneLevel()
	{
		if( droneLevel == PsychicDroneLevel.BadExtreme )
			return;

		droneLevel++;

		string letter = "LetterPsychicDroneLevelIncreased".Translate();
        Find.LetterStack.ReceiveLetter("LetterLabelPsychicDroneLevelIncreased".Translate(), letter, LetterType.BadNonUrgent);

        if( Map == Find.VisibleMap )
		    SoundDefOf.PsychicPulseGlobal.PlayOneShotOnCamera();
	}

    private void DoAnimalInsanityPulse()
    {
        // Find the animals to work with
        IEnumerable<Pawn> nearbyAnimals = 
			Map.mapPawns.AllPawnsSpawned.Where(p => p.RaceProps.Animal 
				&& p.Position.InHorDistOf(Position, AnimalInsaneRadius));

        // Make all animals berserk (60% chance) 
        foreach (var animal in nearbyAnimals)
        {
			animal.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Manhunter);
        }

		Messages.Message( "MessageAnimalInsanityPulse".Translate(), this, MessageSound.Negative );

		if( Map == Find.VisibleMap )
		{
			Find.CameraDriver.shaker.DoShake(4.0f);
			SoundDefOf.PsychicPulseGlobal.PlayOneShotOnCamera();
		}
    }
}}
